#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlTypes;
using System.IO;
using System.Text.RegularExpressions;
using Newtonsoft.Utilities.Collections;
using Newtonsoft.Utilities.Miscellaneous;
using System.Globalization;
using System.Web.UI;
using System.Linq;

namespace Newtonsoft.Utilities.Text
{
  public static class StringUtils
  {
    public const string CarriageReturnLineFeed = "\r\n";
    public const string Empty = "";
    public const char CarriageReturn = '\r';
    public const char LineFeed = '\n';
    public const char Tab = '\t';

    /// <summary>
    /// Determines whether the SqlString is null or empty.
    /// </summary>
    /// <param name="s">The string.</param>
    /// <returns>
    /// 	<c>true</c> if the SqlString is null or empty; otherwise, <c>false</c>.
    /// </returns>
    public static bool IsNullOrEmpty(SqlString s)
    {
      if (s.IsNull)
        return true;
      else
        return string.IsNullOrEmpty(s.Value);
    }

    /// <summary>
    /// Nulls an empty string.
    /// </summary>
    /// <param name="s">The string.</param>
    /// <returns>Null if the string was null, otherwise the string unchanged.</returns>
    public static string NullEmptyString(string s)
    {
      return (string.IsNullOrEmpty(s)) ? null : s;
    }

    /// <summary>
    /// Creates a StringWriter with the specified capacity.
    /// </summary>
    /// <param name="capacity">The capacity of the StringWriter.</param>
    /// <returns></returns>
    public static StringWriter CreateStringWriter(int capacity)
    {
      StringBuilder sb = new StringBuilder(capacity);
      StringWriter sw = new StringWriter(sb);

      return sw;
    }

    /// <summary>
    /// Gets the length of a string, returning null if the string is null.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static int? GetLength(string value)
    {
      if (value == null)
        return null;
      else
        return value.Length;
    }

    /// <summary>
    /// Returns the specified char's unicode string.
    /// </summary>
    /// <param name="c">The c.</param>
    /// <returns></returns>
    public static string ToCharAsUnicode(char c)
    {
      using (StringWriter w = new StringWriter())
      {
        WriteCharAsUnicode(w, c);
        return w.ToString();
      }
    }

    /// <summary>
    /// Writes the specified char's unicode string to a TextWriter.
    /// </summary>
    /// <param name="writer">The writer.</param>
    /// <param name="c">The c.</param>
    public static void WriteCharAsUnicode(TextWriter writer, char c)
    {
      ValidationUtils.ArgumentNotNull(writer, "writer");

      char h1 = MathUtils.IntToHex((c >> 12) & '\x000f');
      char h2 = MathUtils.IntToHex((c >> 8) & '\x000f');
      char h3 = MathUtils.IntToHex((c >> 4) & '\x000f');
      char h4 = MathUtils.IntToHex(c & '\x000f');

      writer.Write('\\');
      writer.Write('u');
      writer.Write(h1);
      writer.Write(h2);
      writer.Write(h3);
      writer.Write(h4);
    }

    public static StringBuilder AppendDelimited(this StringBuilder sb, string text)
    {
      return AppendDelimited(sb, text, ", ");
    }

    public static StringBuilder AppendDelimited(this StringBuilder sb, string text, string delimit)
    {
      ValidationUtils.ArgumentNotNull(sb, "sb");

      if (sb.Length > 0)
        sb.Append(" ");

      return sb.Append(text);
    }

    public static List<string> SplitOnWhiteSpace(string s, bool removeEmptyEntries)
    {
      if (string.IsNullOrEmpty(s))
        return new List<string>() { s };

      List<string> parts = new List<string>();

      int previousWhiteSpaceEndIndex = 0;
      for (int i = 0; i < s.Length; i++)
      {
        if (char.IsWhiteSpace(s[i]))
        {
          bool partEmpty = ((i - previousWhiteSpaceEndIndex) == 0);

          if (!partEmpty)
          {
            parts.Add(s.Substring(previousWhiteSpaceEndIndex, i - previousWhiteSpaceEndIndex));
            previousWhiteSpaceEndIndex = i + 1;
          }
          else
          {
            if (!removeEmptyEntries)
              parts.Add(string.Empty);

            previousWhiteSpaceEndIndex = i + 1;
          }
        }
      }

      if (previousWhiteSpaceEndIndex < s.Length)
      {
        parts.Add(s.Substring(previousWhiteSpaceEndIndex, s.Length - previousWhiteSpaceEndIndex));
      }

      if (char.IsWhiteSpace(s[s.Length - 1]))
      {
        if (!removeEmptyEntries)
          parts.Add(string.Empty);
      }


      return parts;
    }
  }
}